#pragma once


enum
{
	MONITOR_ERR_SUCCESS	= 0,
	MONITOR_ERR_WARN				= 0x0F000000,
	MONITOR_WARN_ALREADY_STARTED,
	MONITOR_WARN_ALREADY_STOPED,
	MONITOR_WARN_TARGET_EMPTY,

	MONITOR_ERR_FAIL				= 0xF0000000,
	MONITOR_ERR_OUT_OF_MEMORY,
	MONITOR_ERR_FAIL_TO_CREATE_THREAD,
	MONITOR_ERR_FAIL_TO_CREATE_IOPORT,
	MONITOR_ERR_FAIL_TO_MONITOR,
	MONITOR_ERR_FAIL_TO_OPEN_DIR
};


typedef enum
{
	CHANGE_ADD			= 1,
	CHANGE_REMOVE,
	CHANGE_MODIFY,
	CHANGE_RENAME_OLD,
	CHANGE_RENAME_NEW
} CHANGEMODE;


#define		MONITOR_BUF_SIZE	4096


typedef struct _MONITOR_INFO
{
	OVERLAPPED	stOverlapped;
	LPVOID		lpExtra;
	CHANGEMODE	enCMode;
	char		aBuf[MONITOR_BUF_SIZE];

} MONITOR_INFO, *PMONITOR_INFO;

typedef struct _MONITOR_RESULT
{
	CHANGEMODE	enChange;
	int			nMonitorID;
	TCHAR		szTarget[MAX_PATH];
	~_MONITOR_RESULT()
	{
		TRACE(_T("_MONITOR_RESULT instance destroyed.\n"));
	}
} MONITOR_RESULT, *PMONITOR_RESULT;


class CMonitor
{
public:
	CMonitor	(void);
	~CMonitor	(void);

	BOOL	IsStart	(void)			{ return m_bIsStarted; }
	int		GetID	(void)			{ return m_nID; }
	void	SetID	(int id)		{ m_nID = id; }
	int		Start	(TCHAR *pszDir);
	int		Stop	(void);

public:
	// static functions
	static TCHAR *			ConvertChangeModeToString	(CHANGEMODE enCMode);

private:
	static void				CALLBACK MonitorCallback	(DWORD, DWORD, LPOVERLAPPED);
	static unsigned WINAPI	MonitorThread				(LPVOID arg);

private:
	// internal functions
	BOOL	_TryMonitoring		(void);

private:
	int				m_nID;
	TCHAR			m_szDirName[MAX_PATH];
	HANDLE			m_IoPort;
	HANDLE			m_hTarget;
	HANDLE			m_hThread;
	PMONITOR_INFO	m_pstMonitorInfo;
	BOOL			m_bIsStarted;
};
